|
home |
Notes on iFP firmware encryption
StatusiRiver's iFP device firmware is encrypted.. which isn't a big surprise because iHP's firmware is encrypted. Analysis has shown us that there are some popular 16-byte strings. After a careful look, we noticed these blocks fit together.. and came up with these 256 bytes:
0x23, 0xd0, 0xef, 0x42, 0x54, 0x4d, 0xa5, 0x23 , 0xae, 0x69, 0x92, 0x47, 0x2e, 0x5a, 0x9c, 0x05, 0xb2, 0x0e, 0x96, 0x97, 0xdb, 0x19, 0xbb, 0x84 , 0xc2, 0xe7, 0x28, 0x55, 0x23, 0xa0, 0x90, 0x55, 0x62, 0x99, 0x18, 0x0c, 0x80, 0x21, 0x9c, 0x52 , 0x1f, 0x06, 0xe7, 0x4a, 0x54, 0x52, 0x36, 0x53, 0xf6, 0xbf, 0x11, 0x90, 0x8b, 0xaf, 0x91, 0x81 , 0x6a, 0x3d, 0x15, 0xa5, 0xde, 0x83, 0x4a, 0x66, 0xfe, 0x47, 0x47, 0xa6, 0x35, 0xea, 0x6b, 0x66 , 0x02, 0xaf, 0x95, 0x59, 0x54, 0xb9, 0xfa, 0x0f, 0xb8, 0xf4, 0x2a, 0xb8, 0x7b, 0xb3, 0x2c, 0x66 , 0xe9, 0xa5, 0xfe, 0xfe, 0x33, 0x0a, 0x31, 0x90, 0x99, 0x42, 0x33, 0x48, 0x0a, 0x8f, 0x2a, 0x23 , 0x6b, 0x42, 0x33, 0x1f, 0x3c, 0x23, 0x81, 0x6c, 0xe0, 0x5e, 0x81, 0xf1, 0xa8, 0x25, 0xc9, 0x90 , 0x90, 0x6f, 0x55, 0xc9, 0x2a, 0x2c, 0xb4, 0xc0, 0x82, 0x21, 0xa9, 0x33, 0x6f, 0x70, 0x10, 0xae , 0x39, 0x2a, 0x1a, 0x28, 0xac, 0x8d, 0xb0, 0x78, 0xaa, 0x1e, 0x90, 0x2a, 0xfe, 0x97, 0x2c, 0x8f , 0xfa, 0x86, 0xd4, 0x2a, 0xbd, 0xaf, 0x20, 0xb2, 0x69, 0x48, 0x14, 0xb5, 0xbf, 0xdc, 0xfd, 0xb1 , 0xbe, 0xed, 0x19, 0x4c, 0x16, 0x0a, 0xdd, 0x4d, 0xa1, 0x45, 0xa4, 0x83, 0xdc, 0xf3, 0x0c, 0xfa , 0x16, 0x0a, 0xe8, 0x20, 0x30, 0x5d, 0x5b, 0x42, 0x5d, 0x5b, 0x98, 0x01, 0x1f, 0x43, 0xb5, 0xf3 , 0x71, 0x52, 0xaa, 0x8c, 0xae, 0x84, 0x3d, 0x40, 0xdd, 0x06, 0x03, 0xed, 0x9d, 0x92, 0x33, 0xc8 , 0x0d, 0x90, 0xfb, 0xc4, 0x59, 0xf0, 0xc1, 0xd2, 0x5a, 0xd2, 0xbb, 0x5f, 0x68, 0xd5, 0x0d, 0x7c , 0x84, 0xf1, 0x58, 0x5a, 0x2c, 0xb5, 0x32, 0x68, 0xc6, 0xd2, 0x48, 0x75, 0x03, 0x9d, 0x8d, 0xd8 , 0xee, 0xec, 0x0a, 0xb5, 0x10, 0xf6, 0x11, 0xbd They always occur at the same offsets within 256-byte blocks. It's suspected that these bytes are "zero"s. (Yes, we've tried xoring the entire file with the above 256 block.. doesn't do much.) LinusNielsenFeltzing: For what it's worth, all versions of the iFP5xx firmware .hex file start with the same 13 bytes: 0x39, 0xb0, 0x5d, 0xed, 0x12, 0x0d, 0xab, 0x5e, 0x85, 0xf2, 0x44, 0x5c, 0x2e Also, the first 512 byte block differs a lot between the versions. This might mean that the first 512 bytes is a checksum array or something. I compared the first 128k of the US and EU versions of the iFP5xxT factory 1.00 firmware. Very few differences up to about 0x11490, where the files go totally apart. In fact, most firmware versions differ very little in the beginning, except for the first 512 bytes. The first 32 bytes of the firmware is very likely to be the exception vector table. If I understand it correctly, ARM exception vectors consist of an unconditional branch instruction. The ARM7 opcode of an unconditional branch is 0xEAxxxxxx, where xxxxxx is the offset. The reset vector offset is likely to be small, so we can probably assume that the second byte of the opcode is 0x00. The Reserved vector is probably 0x00000000. This gives us a nice beginning of a crib: ea, 00, ??, ??, ea, ??, ??, ??, ea, ??, ??, ??, ea, ??, ??, ??, ea, ??, ??, ??, 00, 00, 00, 00, ea, ??, ??, ??, ea, ??, ??, ?? GeoffOakham - 10 Mar 2005: Interesting idea about the checksum. There seems to be 240 bytes of "random" data at the begining, and the firmware files each have around 10778 blocks of 256 bytes. iHP had 1byte checksums for each 256 block, so iFP firmware obviously does something different. Any guesses as to how this checksum might work?
Ideas & discussionTaking a page out of Dave's book, I've converted various firmwares into graphics. My results are in a separate page because they're quite large: IfpCryptanalysisGraphic1. GeoffOakham - 11 Mar 2005: I've been studying various graphics, and there appears to be something happening every 51 bytes. (In 512pixel wide bitmaps, these looks like lines.) GeoffOakham - 12 Mar 2005: Confirmed. Each 256 byte block seems to be made of 5 groups of 51 + 1 extra byte. Also, the last byte of each sub-group, and the last byte of the whole block seem to be different from the others. They might be checksums: 50 bytes data, 1 byte checksum... and ending with a whole-block checksum. Take a look in the red channel of the attached picture. Green is the "raw data", red is 255 when the byte matches the [suspected] key, and blue is 255 when the byte one of the ones in the suspected key. That sounds more complicated than it has to: but the red highlights data that is probably zero. RaulAguaviva - 14 Mar 2005: Added a SimpleFirmwareCrack TomekMalesinski - 17 Jun 2005: I think I have decrypted the firmware. After looking at differences between the US and EU versions of the firmware and doing some frequency analysis (the last byte of an ARM opcode is usually 0xe5 or 0xe3) I assumed that the encrypted value of a byte depends only on its decrypted value and its position within a 256 byte block. So, in order to decrypt the firmware we need to know the function decrypt(position, byte), where position is a number between 0 and 249 and byte is between 0 and 255. Most probably there is a simple formula describing the function, but I have not tried to find one yet. Zeroes are encrypted in the way shown above on this page. Knowing which bytes are zero and which are not I was looking for lookup tables from the Tremor decoder. The tables were big enough to be found at unique positions. Those tables were stored at different positions in different versions of the firmware, so from each firmware I could recover decrypt function values for some arguments. After that I could decode 70% of the firmware. Looking at an incomplete table of the function I noticed that some rows are just some other rows xored by some number. More precisely, for some numbers a and b there was a number x such that decrypt(a, i) = decrypt(b, i) xor x for all i. I found pairs of rows for which the above condition was, as far as I could tell from the incomplete table, satisfied. Then I assumed that if the condition was true for most numbers in the row, then it must have been satisfied by the rest of the numbers. This way I completed the table. I am not sure whether all the 250*256 values found by me are correct. The decrypted firmware looks quite right, but as every single value in the table affects only about 20 bytes in the firmware, it is difficult to spot mistakes. To make sure that the decryption was correct someone should find a simple formula for the decrypt function or find the decryption procedure in the firmware. I have not investigated what the meaning of those extra bytes in 256 byte blocks is. Probably they are checksums. I attach the decryption program together with values of the function. Compile the program, put the key.bin file in the current directory and run:
ifp_decode in.hex out.hex CoreyCason - 20 Jul 2005: After looking at Dave's iHPBMP utility (and source), I wondered if the iFP f/w images would decode the same way as in the iHP-120 f/w. I wrote a crude app (based on Dave's algorithms) to process the whole file as if it were stored as bitmap data (I used v1.25, decoded). Of course, the whole file isn't encoded as bitmap data, but I figured something might jump out at me. It turns out that a large portion of the firmware image is devoted to non-english fonts, and the tail end of the firmware holds most (if not all) of the images used (see attached image). I've extracted a few random images. (Update 22 Jul 2005): Reloaded bitmap_decoded.gif after processing it based on 1 bit-per-pixel encoding (previously based it on 2 bpp). I have successfully modified images and flashed my ifp-899 w/ modded firmware (updated images) with no ill effects. I have modified Dave's ihpbmp code to extract and change out images in the ifp firmwares and will share it when I get it cleaned up.
PeopleDaveHooper, RaulAguaviva, and GeoffOakham are currently working on this problem. Send us email if you'd like to contribute.
References
|